/**
 * Wrapper class for autocomplete plugin upon JUI autocomplete widget
 * @author Smyle
 */
(
	function($, undefined) {

		$.widget("qui.suggest", $.ui.autocomplete, {
			version: '0.0.1',
			options: {
				// 请求地址
				url: '',

				// 请求类型
				method: 'get',

				// 是否自动选择地一条
				autoFocus: true,

				// 是否可以多选
				multiple: true,

                //拖过enter 快速添加
                quickAdd:false,

				// 是否校验结果
				validate: false,

				multipleValid: false,

				// 是否onblur时清空无效结果
				clearInvalid: true,

				noResult: '对不起，没有这个结果',

				otherParam: {},

				// the field to save in sync with data-id attribute
				valueKey: 'id',

				// the raw text used to render each suggest item
				// NOTE: the final displayed text is saved in the _displayKey specified 
				// field of each item
				labelKey: 'label',

				needFooter: true,
                // 开启filter
                autoFilter: true,

				parseValue: function() {
					var val = this.element.val(),
						ret = [],
						items = null,
						itemData = null,
						options = self.options;

					if (val) {
						items = val.split(';');
						$.each(
							items, function(i, item) {
								item = item.split(',');
								itemData = {};
								itemData[options.labelKey] = item[1];
								itemData[options.valueKey] = item[0];
								ret.push(itemData);
							}
						);
					}
					this._value('');
					return ret;
				},

				/**
				 * @desc handler for create event
				 */
				create: function(event, ui) {
					$(this).suggest('init');
				},

				/**
				 * @desc handler to reorganize raw data, the return value will
				 * be used to render the suggest list
				 * @return {Array}
				 */
				process: function(json) {
					var ret = [],
						data = $.isArray(json) ? json : json.data,
						self = this,
						options = self.options,
						itemData = null;
					if (!data) {
						return [];
					}
					$.map(data, function(item) {
						if ('string' === typeof item) {
							itemData = {};
							itemData[options.valueKey] = item;
							itemData[options.labelKey] = item;
							itemData[self._displayKey] = item;
							ret.push(itemData);
						} else {
							item[self._displayKey] = item[options.labelKey];
							ret.push(item);
						}
					});
					return ret;
				},

				/**
				 * @desc used to highlight key word, the highlight should process
				 * the label key and save it back in the storeKey， the store key
				 * is generally the displayed key defined by suggest plugin
				 */
				highlight: function(data, storeKey, term) {
					var self = this,
						options = self.options;
					data.forEach(function(item, i) {
						var label = null;
						if ('string' !== typeof item) {
							key = options.labelKey;
							label = item[key];
							if (!label || !term) {
								return;
							}
							try {
								item[self._displayKey] = item[key].replace(new RegExp('(' + term + ')', 'ig'), '<b>$1</b>');
							} catch (ex) {}
						} else {
							data[i] = item.replace(new RegExp('(' + term + ')', 'ig'), '<b>$1</b>');
						}
					});
				}
			},

			/**
			 * return an array of processed items which is used to render the suggest pop list
			 *	@return {Array}
			 */
			getResultData: function() {
				return this.result;
			},

			/**
			 * @desc send ajax request to remote suggest service
			 */
			_getSuggestData: function(url, method, params, callback) {
				$.ajax({
					url: url,
					dataType: 'json',
					data: params,
					cache: false,
					method: method,
					success: function(data) {
						if (callback) {
							callback.call(this, data);
						}
					},
					error: function(data) {
						if (callback) {
							callback.call(this, data);
						}
					}
				});
			},

			/**
			 * entrance for suggest to handle the request process
			 * @param {Function} requset JSON in format of { term: value }
			 * @param {Function} response the function to handle the response of request
			 * @param {Object} data raw array used to render the suggest list
			 */
			_handleResponse: function(request, response, data) {
				var self = this,
					options = self.options,
					term = $.trim(request.term),
					dataProcess = options.process,
					ret = dataProcess.call(self, data, term);

			//	ret = $.ui.autocomplete.filter(ret, request.term);
                ret = options.autoFilter ? $.ui.autocomplete.filter(ret, term) : ret;
				if (options.highlight) {
					options.highlight.call(self, ret, self._displayKey, term);
				}

				self.result = ret;
				response(ret);
			},

			/**
			 * overide original JUI autocomplete source initializer
			 */
			_initSource: function() {
				var array, self = this;
				if ($.isArray(self.options.source)) {
					array = self.options.source;
					self.source = function(request, response) {
						self._handleResponse(request, response, array);
					};
				} else if (typeof this.options.source === "string") {
					self.options.url = url = self.options.source;
					self.source = self.__source;
				} else {
					self.source = self.options.source;
				}
			},

			/**
			 * invoked when there is a need to send an ajax suggest
			 * @param {Object} request JSON in format of { term: value }
			 * @param {Function} response the function to handle the response of request
			 */
			__source: function(request, response) {
				var self = this,
					options = self.options,
					term = $.trim(request.term),
					url = null,
					getParam = null,
					param = {};

				if (!term) {
					return null;
				}

				if (!options.ignoreWord) {
					//传递 word  term
					param = {
						word: term
					};
				}

				param = $.extend(true, options.otherParam, param);

				url = options.url;
				getParam = options.getParam;
				if (getParam) {
					if ($.isFunction(options.getParam)) {
						param = $.extend(true, param, getParam.call(self, term));
					} else if ($.isPlainObject(getParam)) {
						param = $.extend(true, param, getParam);
					}
				}

				self._getSuggestData(url, options.method, param, $.proxy(self._handleResponse, self, request, response));
			},

			_create: function() {
				var $this = this.element;
				$this.wrap('<span class="ui-front ui-suggest"></span>');
				this._super();
				$this.on('suggestresponse', function(event, ui) {
					var content = ui.content;
					$this.suggest('validate', content);
				}).on('suggestselect', function(event, ui) {
					return $this.suggest('setValue', ui.item);
				}).on('suggestsearch', function(event, ui) {
					return $this.suggest('multiplesearch');
				});
			}
		});
	}(jQuery)
);